#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "ProducerConsumerUtilities.h"
#include "Consumer.h"
#include "Producer.h"

//定义生产者和消费者的数量
#define PRODUCER_NUMBER 2
#define CONSUMER_NUMBER 10

int main(int argc, char *argv[]){
	int idx = 0;
	//分配存储ThreadStruct_t的数组用于传递参数给每个线程
	ThreadStruct_t    *producerThreadStructPtr    =    (ThreadStruct_t*)malloc(sizeof(ThreadStruct_t)*PRODUCER_NUMBER);
	ThreadStruct_t    *consumerThreadStructPtr    =    (ThreadStruct_t*)malloc(sizeof(ThreadStruct_t)*CONSUMER_NUMBER); 				ProducerConsumerManager_t      *producerConsumerMgr      =
	createProducerConsumerManager(); //创建并初始化共享管理器
	
	if(NULL==producerThreadStructPtr||NULL==consumerThreadStructPtr||NULL==producerConsumerMgr)
	{
		perror("malloc fail!\n");
		exit(EXIT_FAILURE);
	}
	
	//循环创建指定数量生产者线程
	for(idx = 0; idx < PRODUCER_NUMBER; ++idx){
		ThreadStruct_t *curProducerThreadStruct = producerThreadStructPtr + idx;
		initThreadStruct(curProducerThreadStruct, producerConsumerMgr, idx);
		pthread_create(&curProducerThreadStruct->tid, NULL, producerThread,(void*)curProducerThreadStruct);
	}
	
	//循环创建指定数量消费者线程
	for(idx = 0; idx < CONSUMER_NUMBER; ++idx){
		ThreadStruct_t *curConsumerThreadStruct = consumerThreadStructPtr + idx;
		initThreadStruct(curConsumerThreadStruct, producerConsumerMgr, idx);
		pthread_create(&curConsumerThreadStruct->tid,NULL,consumerThread, (void *)curConsumerThreadStruct);
	}

	//退出等待，若输入q则退出
	do{
		char aChar = getchar();
		if (aChar == 'q')
		{
			producerConsumerMgr->exit_flag = 1;
		}
	}while(producerConsumerMgr->exit_flag == 0);
	
	//Wait producer threads exit
	//等待所有生产者线程结束
	for(idx = 0; idx < PRODUCER_NUMBER; ++idx){
		ThreadStruct_t *curProducerThreadStruct = producerThreadStructPtr + idx;
		pthread_join(curProducerThreadStruct->tid, NULL);
	}
	for(int i = 0; i < BUFFER_SIZE; i++){
                sem_post(&producerConsumerMgr->full);  // 唤醒可能阻塞的消费者
                sem_post(&producerConsumerMgr->empty); // 唤醒可能阻塞的生产者
        }
	//Wait consumer threads exit
	//等待所有消费者线程结束
	for(idx = 0; idx < CONSUMER_NUMBER; ++idx){
		ThreadStruct_t *curConsumerThreadStruct = consumerThreadStructPtr + idx;
		pthread_join(curConsumerThreadStruct->tid, NULL);
	}
	
	//释放资源
	free(producerThreadStructPtr);
	free(consumerThreadStructPtr);
	semDestroy(&(producerConsumerMgr->mutex));
	semDestroy(&(producerConsumerMgr->full));
	semDestroy(&(producerConsumerMgr->empty));
	free(producerConsumerMgr);
	return 1;
}

